<!--
 * @Author: ssj
 * @Date: 2021-06-26 17:51:15
 * @LastEditors: zss
 * @LastEditTime: 2024-11-07 14:12:15
 * @Description: m2o组件
-->
<template>
  <div class="o-m2o-selector">
    <!-- :clearable="isDropdown" -->
    <!-- :icon="isDropdown ? 'ios-arrow-down' : 'ios-search'" -->
    <!-- :readonly="isDropdown" -->
    <i-input
      v-model="value"
      icon="ios-search"
      ref="input"
      :disabled="isDisabled"
      :placeholder="infotip"
      :class="'align-' + align"
      :title="modelvalue"
      @on-change="onChange"
      @on-blur="onBlur"
      @on-focus="onFocus"
      @on-click="openMagicBox"
      @on-clear="onChange"
      @on-enter="onEnter"
      @mouseleave="onMouseleave"
      @mouseenter="onMouseenter"
    />
  </div>
</template>
<script lang="ts">
import { T_srv, ts, Tsrv, vue } from '@/services';
import { Input } from 'view-design';

@T_srv.comp
export default class oM2oSelector extends vue {
  @T_srv.prop() renderOpts: any;

  // 表内属性
  @T_srv.prop() params: any;

  // 是否disable
  @T_srv.prop({ required: false, default: false }) disabled: boolean;

  // 占位符
  @T_srv.prop({ required: false, default: '' }) placeholder: string;

  // 对应表
  @T_srv.prop({ required: false }) tTable: string;

  // 对应值字段
  @T_srv.prop({ required: false }) tField: string;

  // 对应显示字段
  @T_srv.prop({ required: false }) vField: string;

  // 来源表
  @T_srv.prop({ required: false, default: '' }) sTable: string;

  // 来源字段
  @T_srv.prop({ required: false, default: '' }) sField: string;

  // 下拉
  @T_srv.prop({ required: false, type: Boolean }) dropdown: boolean;

  // 配置
  @T_srv.prop({ required: false }) option: any;

  // 完整功能
  @T_srv.prop({ required: false, default: true }) isFunLayout: boolean;

  // 配置
  @T_srv.prop({ required: false, default: null }) m2ovalue: any; // m2ovalue值

  // 过滤条件
  @T_srv.prop({ required: false, default: null }) filter: object;

  // 数据来源于表格 但使用是在表格外部使用该组件
  @T_srv.prop({ required: false, default: false }) isFromTable: boolean;

  // disabled
  @T_srv.watch('disabled')
  onDisabledChange(val: boolean) {
    this.isDisabled = val;
  }

  @T_srv.watch('params')
  onParamsChange() {
    this.init();
    this.setValue();
    this.initProps();
  }

  @T_srv.watch('renderOpts', { deep: true })
  onRenderOptsChange() {
    this.init();
    this.initProps();
  }

  @T_srv.model('model-change') modelvalue: string | null;

  @T_srv.watch('modelvalue')
  onValueChange(val: string | number | null) {
    this.setValue(val);
  }

  @T_srv.watch('m2ovalue')
  onM2oValueChange(val: string | number | null) {
    this.setValue(val);
  }

  /**
   * 控制属性
   */
  public compName: string = 'oM2oSelector';

  // eslint-disable-next-line no-template-curly-in-string
  private doubleQuotes = '${doubleQuotes}'; // 单引号占位符

  // eslint-disable-next-line no-template-curly-in-string
  private singleQuotes = '${singleQuotes}'; // 双相号占位符

  private isInTable: boolean = false;

  // 是否为table内的组件
  private loading: boolean = false; // mode=1是否正在加载选项

  private value = null;

  // 当前显示值
  private selectedValue = null;

  // 已选择的value
  private selectedM2oValue = null;

  // 已选择的m2o value
  private selectedRow = null;

  private storedValue = null;

  private isDisabled: boolean = false;

  // 是否可写
  private align: string = 'left'; // 对齐方式

  /**
   * 功能属性
   */
  // 自身字段
  private iField: string = '';

  // 对应字段
  private toTable: string = '';

  // 对应值字段
  private toField: string = '';

  // 对应显示字段
  private viField: string = '';

  // 来源表
  private soTable: string = '';

  private isDropdown: boolean = false;

  private m2oConfig: any = {};

  private fieldConfig = [];

  private translateM2o: boolean = false;

  private currentBusId = null;

  private notM2O: boolean = false;

  private delay: number = 0;

  private delayTime: number = 400;

  private isI18n: boolean = false;

  private Tcommand: any = null;

  private G_paramsFromComp: 'oBaseGrid' | 'oBaseForm' = null;

  private initFilter: Array<any> = [];

  // 'mini' —— 跟随模式（小窗口）、'full' —— 窗口模式（窗口）、'' —— 两者皆可
  // private boxMode: 'mini' | 'full' | '' = '';

  private toolbarConf = {
    left: true,
    right: true
  };

  get infotip() {
    if (this.placeholder) {
      return this.placeholder;
    }
    if (this.renderOpts?.props?.placeholder) {
      return this.renderOpts.props.placeholder;
    }
    return '';
  }

  created() {
    this.isInTable = this.tTable === undefined; // 是否为表内
    // if (this.renderOpts?.props?.getTcommand()?.oBaseGrid?.G_compName) {
    //   this.G_paramsFromComp = 'oBaseGrid';
    // } else if (this.renderOpts?.props?.getTcommand()?.oBaseForm?.G_compName) {
    //   this.G_paramsFromComp = 'oBaseForm';
    // } else {
    //   this.$msg({});
    //   console.error('未定义的组件');
    // }
    if (
      !Tsrv.utils.noValue(this.params) &&
      // this.params.hasOwnProperty('property')
      Object.prototype.hasOwnProperty.call(this.params, 'property')
    ) {
      this.G_paramsFromComp = 'oBaseForm';
    } else {
      this.G_paramsFromComp = 'oBaseGrid';
    }

    if (typeof this.renderOpts?.props?.getTcommand === 'function') {
      this.Tcommand = this.renderOpts.props.getTcommand();
      if (typeof this.Tcommand?.isI18nField === 'function') {
        this.isI18n = this.Tcommand.isI18nField(
          this.G_paramsFromComp === 'oBaseForm'
            ? this.params.property
            : this.params.column.property
        );
      } else {
        if (
          Object.prototype.hasOwnProperty.call(this.renderOpts?.props, 'isI18n')
        ) {
          this.isI18n = this.renderOpts.props.isI18n;
        } else {
          Tsrv.getFunConf(this.renderOpts.props.m2oConfig.toTable).then(res => {
            if (res.isErr()) {
              // console.error(res.errmsg);
            } else {
              const cf = res.getReturnData(
                this.renderOpts.props.m2oConfig.toTable
              );
              if (Tsrv.noValue(cf?.funI18nFields)) {
                // o.many2one.toField, o.field
                cf?.funI18nFields.includes(
                  this.renderOpts.props.m2oConfig.toField
                ) && (this.isI18n = true);
              }
            }
          });
        }
      }
    }
    this.handleFieldConfig();
  }

  mounted() {
    this.init();
    this.initProps();
    this.setValue();
    this.addCustomEvents();
  }

  // 重置属性
  private initProps() {
    if (this.isInTable) {
      // disable属性在props中
      // this.isDisabled = this.renderOpts.props.disabled;
      this.isDisabled = this.isFromTable
        ? this.disabled
        : this.renderOpts.props.disabled;

      // 对齐属性在params中
      if (this.params.property) {
        // 查看对齐属性设置
        const items = this.params.$form.items;
        const find = Tsrv.utils.find(
          items,
          el => el.field === this.params.property
        );
        if (find) {
          this.align = find.align || 'left';
        }
      } else {
        this.align = this.params.column.align || 'left';
      }
    } else {
      this.isDisabled = this.disabled;
    }
  }

  /**
   * init 初始化
   */
  private init() {
    if (!this.isInTable) {
      // 非table组件，通过props接收toTable和toField
      this.toTable = this.tTable;
      this.toField = this.tField;
      this.viField = this.vField;
      this.isDropdown = this.dropdown;
      this.fieldConfig = this.option ? this.option : [];

      if (this.viField) {
        this.notM2O = true;
      }

      // QBE
      this.soTable = this.sTable;
      this.iField = this.sField;
    } else {
      let isM2o = this.params.property
        ? this.params.property.indexOf('|') > -1
        : this.params.column.property.indexOf('|') > -1;

      this.isDropdown = this.renderOpts.props.isDropdown || false;
      this.m2oConfig = this.renderOpts.props.m2oConfig || {};
      this.soTable = this.renderOpts.props.funName;
      // 弹窗展示 模式
      // this.boxMode = this.m2oConfig?.mode ? this.m2oConfig.mode : '';

      if (this.m2oConfig.toTable && this.m2oConfig.fields) {
        this.fieldConfig = this.m2oConfig.fields;
        for (let i = 0; i < this.fieldConfig.length; i++) {
          if (this.fieldConfig[i].isReturn === true) {
            this.toField = this.fieldConfig[i].title;
            isM2o = false;
            break;
          }
        }
      }
      if (isM2o) {
        // 从params字段信息中找m2o信息
        const m2oInfo = this.params.property
          ? Tsrv.utils.splitM2OField(this.params.property)
          : Tsrv.utils.splitM2OField(this.params.column.property);
        this.iField = m2oInfo.field;
        this.toTable = m2oInfo.toTable;
        this.toField = m2oInfo.toField;
      } else {
        this.notM2O = true;
        this.toTable = this.m2oConfig.toTable;
        this.translateM2o = !!this.m2oConfig.i18n;
      }
    }
  }

  /**
   * 重置值，table组件
   */
  public resetValue() {
    if (!this.isInTable) {
      this.setValue(null);
      this.setTableValue(null);
    } else {
      this.value = null;
    }
  }

  /**
   * setValue 设置输入框的值
   * @param {null | string | undefined} val @default undefined - 值
   */
  public setValue(val: null | string | number | undefined = undefined) {
    if (this.isInTable) {
      // 表内元素，设置显示值，已选择值，已选择m2o值
      if (this.params.property) {
        if (!this.notM2O) {
          this.selectedValue = this.params.data[this.iField];
          this.selectedM2oValue = this.params.data[this.params.property];
          this.value =
            val !== undefined
              ? val
              : // : Tsrv.getI18nBySrv(this.params.data[this.params.property]);
                this.i18n(this.params.data[this.params.property]);
        } else {
          this.value =
            val !== undefined ? val : this.params.data[this.params.property];
        }
      } else {
        if (!this.notM2O) {
          this.selectedValue = Tsrv.utils.toInteger(
            this.params.row[this.iField]
          );
          this.selectedM2oValue = this.params.row[this.params.column.property];
          this.value =
            val !== undefined
              ? val
              : // : Tsrv.getI18nBySrv(this.params.row[this.params.column.property]);
                this.i18n(this.params.row[this.params.column.property]);
        } else {
          this.value =
            val !== undefined
              ? val
              : this.params.row[this.params.column.property];
        }
      }
    } else {
      // 非表元素，设置显示值，不存在已选择值，只存在已选择m2o值
      if (!this.notM2O) {
        this.value =
          val !== undefined
            ? this.i18n(val as string) // ? Tsrv.getI18nBySrv(val as string)
            : this.i18n(this.modelvalue); // : Tsrv.getI18nBySrv(this.modelvalue);
      } else {
        this.value = val !== undefined ? val : this.modelvalue;
      }
      this.selectedM2oValue = val !== undefined ? val : this.modelvalue;
      if (this.selectedM2oValue === '') this.selectedRow = null;
    }
  }

  /**
   * setTableValue 设置表的值，table组件
   * @param {string | null)} val - 值
   */
  private setTableValue(val: string | null) {
    if (this.isInTable) {
      if (this.params.property) {
        this.params.data[this.params.property] = val;
        if (val === null && !this.notM2O) this.params.data[this.iField] = null;
      } else {
        this.params.row[this.params.column.property] = val;
        if (val === null && !this.notM2O) this.params.row[this.iField] = null;
      }
    }
  }

  private regExSingleQuotes = new RegExp(
    this.singleQuotes.replace('$', '\\$'),
    'g'
  );

  private regExDoubleQuotes = new RegExp(
    this.doubleQuotes.replace('$', '\\$'),
    'g'
  );

  /**
   * openMagicBox 打开magicbox查询
   * @param {any} e - 当前dom对象，用于定位
   * @param {string} mode @default full - 打开magicbox模式
   */
  private openMagicBox(e: any, mode: string = 'full') {
    if (this.currentBusId) {
      clearTimeout(this.delay);
      this.delay = setTimeout(() => {
        if (this.$bus._events[this.currentBusId])
          this.$bus.$emit(this.currentBusId, {
            globalSearch: e?.target?.value || ''
          });
      }, this.delayTime);
    } else {
      this.fieldConfig = this.getFieldConfig();
      if (!this.isDisabled) {
        let row;
        let property;
        if (this.isInTable) {
          if (this.params.property) {
            row = this.params.data;
            property = this.params.property;
          } else {
            row = this.params.row;
            property = this.params.column.property;
          }
        } else {
          row = '';
          property = '';
        }
        const input = (this.$refs.input as Vue).$el;
        if (mode === 'full' && !this.isDropdown)
          this.showMagicBox(row, property, input, e.target.value);
        else this.showMiniMagicBox(row, property, input, e.target.value);
        // if (this.boxMode === 'full') {
        //   this.showMagicBox(row, property, input, e.target.value);
        // } else if (this.boxMode === 'mini') {
        //   this.showMiniMagicBox(row, property, input, e.target.value);
        // } else {
        //   if (mode === 'full' && !this.isDropdown)
        //     this.showMagicBox(row, property, input, e.target.value);
        //   else this.showMiniMagicBox(row, property, input, e.target.value);
        // }
      }
    }
  }

  /**
   * showMagicBox
   */
  public showMagicBox(row: any = '', property: string = '', event: any, value) {
    let m2oFilter;
    if (!Tsrv.noValue(this.m2oConfig?.filter)) {
      const filter = this.m2oConfig.filter
        .replace(this.regExSingleQuotes, "'")
        .replace(this.regExDoubleQuotes, '"');
      if (Tsrv.utils.isJSONString(filter)) {
        m2oFilter = JSON.parse(filter);
      } else {
        this.$msg('-50015,FE,90,*filter#');
      }
    }
    const filter = {
      globalSearch: value,
      initSearch: m2oFilter ?? {}
    };
    // if (!Tsrv.utils.noValue(this.filter)) {
    //   filter['initSearch'] = this.filter;
    // }
    this.handleInitFilter(filter);
    const config = {
      // isFunLayout: this.isFunLayout,
      isFunLayout: Tsrv.getx(
        this.renderOpts,
        'props.m2oConfig.isFunLayout',
        this.isFunLayout
      ),
      tableConfig: this.fieldConfig,
      customSearch: this.m2oConfig.customSearch,
      fromFunName: this.soTable,
      fromFieldName: this.iField,
      isInTable: true
    };
    if (!Tsrv.noValue(this.m2oConfig?.boxSize)) {
      config['boxSize'] = this.m2oConfig.boxSize;
    }
    if (!Tsrv.noValue(this.m2oConfig?.toolbar)) {
      config['toolbarConfig'] = this.m2oConfig.toolbar;
    }

    this.currentBusId = `magicbox_${this.$store.getters.ModalCount + 1}`;
    Tsrv.utils
      .createModal('oMagicBox', {
        // source: { funid: null, field: this.toTable, limit: 999, filter },
        source: {
          funid: null,
          isRule: true, // 所有查询都有规则策略 modify by wiz 210609
          field: this.toTable,
          limit: 999,
          filter
        },
        config
      })
      .then(data => {
        this.currentBusId = null;
        if (data && data.length > 0) {
          // 处理选择的数据
          if (this.isInTable) {
            // 直接设置表内数据
            if (this.m2oConfig.multiConnect) {
              row[property] = data
                .map(el => el[this.toField])
                .join(this.m2oConfig.multiConnect);
            } else {
              row[property] = this.translateM2o
                ? // ? Tsrv.getI18nBySrv(data[0][this.toField])
                  this.i18n(data[0][this.toField])
                : data[0][this.toField];
              if (!this.notM2O) {
                row[this.iField] = data[0].id;
              }
            }
            // 更新显示值
            this.setValue();
            this.selectedRow = data[0];

            if (data.length > 1 && !this.m2oConfig.multiConnect) {
              data.shift();
              const insertData = [];
              data.forEach(el => {
                const d = {};
                d[property] = el[this.toField];
                if (!this.notM2O) {
                  d[this.iField] = el.id;
                }
                insertData.push(d);
              });
              this.insertRow(insertData);
            }
          } else {
            // 设置显示值
            if (this.m2oConfig.multiConnect && data.length > 1) {
              this.setValue(
                data
                  .map(el => el[this.toField])
                  .join(this.m2oConfig.multiConnect)
              );
            } else {
              this.setValue(data[0][this.toField]);
              this.selectedRow = data[0];
            }
          }
          this.onDoChange();
        }
      });
  }

  public showMiniMagicBox(row: any, property: string, event: any, value) {
    const bound = Tsrv.utils.clone(event.getBoundingClientRect(), true);
    const config = {
      isMini: true,
      miniBound: bound,
      customSearch: this.m2oConfig.customSearch,
      tableConfig: this.fieldConfig,
      isDropdown: this.isDropdown,
      fromFunName: this.soTable,
      fromFieldName: this.iField,
      isInTable: true
    };
    if (!Tsrv.noValue(this.m2oConfig?.boxSize)) {
      config['boxSize'] = this.m2oConfig.boxSize;
    }
    if (!Tsrv.noValue(this.m2oConfig?.toolbar)) {
      config['toolbarConfig'] = this.m2oConfig.toolbar;
    }
    let m2oFilter;
    if (!Tsrv.noValue(this.m2oConfig?.filter)) {
      const filter = this.m2oConfig.filter
        .replace(this.regExSingleQuotes, "'")
        .replace(this.regExDoubleQuotes, '"');
      if (Tsrv.utils.isJSONString(filter)) {
        m2oFilter = JSON.parse(filter);
      } else {
        this.$msg('-50015,FE,90,*filter#');
      }
    }
    const filter = {
      globalSearch: value,
      initSearch: m2oFilter ?? {}
    };
    // if (!Tsrv.utils.noValue(this.filter)) {
    //   filter['initSearch'] = this.filter;
    // }
    this.handleInitFilter(filter);
    this.currentBusId = `magicbox_${this.$store.getters.ModalCount + 1}`;
    Tsrv.utils
      .createModal('oMagicBox', {
        source: { funid: null, field: this.toTable, limit: 999, filter },
        config
      })
      .then(data => {
        this.currentBusId = null;
        if (data && data.length > 0) {
          if (this.isInTable) {
            if (this.m2oConfig.multiConnect) {
              row[property] = data
                .map(el => el[this.toField])
                .join(this.m2oConfig.multiConnect);
            } else {
              row[property] = this.translateM2o
                ? // ? Tsrv.getI18nBySrv(data[0][this.toField])
                  this.i18n(data[0][this.toField])
                : data[0][this.toField];
              if (!this.notM2O) {
                row[this.iField] = data[0].id;
              }
            }
            this.setValue();
            this.selectedRow = data[0];

            if (data.length > 1 && !this.m2oConfig.multiConnect) {
              data.shift();
              const insertData = [];
              data.forEach(el => {
                const d = {};
                d[property] = el[this.toField];
                if (!this.notM2O) {
                  d[this.iField] = el.id;
                }
                insertData.push(d);
              });
              this.insertRow(insertData);
            }
          } else {
            if (this.m2oConfig.multiConnect && data.length > 1) {
              this.setValue(
                data
                  .map(el => el[this.toField])
                  .join(this.m2oConfig.multiConnect)
              );
            } else {
              this.setValue(data[0][this.toField]);
              this.selectedRow = data[0];
            }
          }
          this.onDoChange();
        }
      });
  }

  /**
   * @description: 整理 初始筛选条件
   * @param {*} filter
   * @return {*}
   * @author: zss
   * @Date: 2024-10-25 11:04:32
   * @LastEditors: zss
   * @LastEditTime: Do not edit
   */
  private handleInitFilter(filter: object) {
    const initSearch = new ts.T_filter();
    if (!Tsrv.noValue(filter['initSearch'])) {
      const initFilter = filter['initSearch'];
      // 数组形式的过滤
      if (Object.prototype.toString.call(initFilter) === '[object Array]') {
        initSearch.filter = initSearch.parseAND([
          initSearch.parseAND(initFilter)
        ]);
      }
      if (Object.prototype.toString.call(initFilter) === '[object Object]') {
        // 过滤表达式、I_fv的过滤
        // if (JSON.stringify(initFilter).indexOf('$') > -1) {
        //   initSearch.filter = initSearch.parseAND([
        //     initSearch.parseAND(initFilter)
        //   ]);
        // }
        // // I_fv的过滤
        // if (Object.keys(initFilter).length === 2 && ) {
        //   initSearch.filter = initSearch.parseAND([
        //     initSearch.parseAND(initFilter)
        //   ]);
        // }
        initSearch.filter = initSearch.parseAND([initFilter]);
      }
    }
    if (this.isInTable) {
      // 2、basegrid中若设置的有初始筛选条件，则添加到筛选条件中
      if (
        typeof this.Tcommand?.getFieldFilter === 'function' &&
        this.Tcommand.getFieldFilter('m2oFilter')
      ) {
        const find = this.Tcommand.getFieldFilter('m2oFilter').find(
          el => el?.field === this.iField
        );
        if (Tsrv.noValue(find)) {
          return;
        }
        const aimFilter = find.filter;
        if (!Tsrv.noValue(aimFilter)) {
          if (!Tsrv.noValue(initSearch.filter)) {
            initSearch.filter = initSearch.parseAND([
              initSearch.filter,
              initSearch.parseAND([aimFilter])
            ]);
          } else {
            initSearch.filter = initSearch.parseAND([aimFilter]);
          }
        }
      }
    } else {
      // 1、prop：若存在初始筛选条件，则添加到筛选条件中
      if (!Tsrv.noValue(this.filter)) {
        if (!Tsrv.noValue(initSearch.filter)) {
          initSearch.filter = initSearch.parseAND([
            initSearch.filter,
            initSearch.parseAND([this.filter])
          ]);
        } else {
          initSearch.filter = initSearch.parseAND([this.filter]);
        }
      }
    }

    // 3、其他原因插入的初始筛选条件 this.initFilter
    if (!Tsrv.noValue(this.initFilter)) {
      if (!Tsrv.noValue(initSearch.filter)) {
        initSearch.filter = initSearch.parseAND([
          initSearch.filter,
          initSearch.parseAND(this.initFilter)
        ]);
      } else {
        initSearch.filter = initSearch.parseAND(this.initFilter);
      }
    }

    filter['initSearch'] = initSearch;
  }

  // 根据功能字段配置，添加初始化过滤条件
  private handleFieldConfig() {
    if (!Tsrv.utils.noValue(this.renderOpts?.props?.m2oConfig)) {
      const funName = this.renderOpts.props.funName;
      const funInfo = Tsrv.getFunInfo(
        Tsrv.getMainFunInfoByFunName(funName)?.mainFun
      );
      const currentRow =
        this.G_paramsFromComp === 'oBaseGrid'
          ? this.params.row
          : this.params.data;
      // 有级联查询规则
      if (!Tsrv.utils.noValue(this.renderOpts.props?.cascadeFilter)) {
        const p = {
          // inputArgs: [
          //   { name: 'funName', dataType: 'string', value: funName ?? '' },
          //   {
          //     name: 'fieldName',
          //     dataType: 'string',
          //     value:
          //       // this.params.$table.getTableColumn().fullColumn[
          //       //   this.params.columnIndex
          //       // ].title ?? ''
          //       this.params.column.property ?? ''
          //   },
          //   {
          //     name: 'currRow',
          //     dataType: 'string',
          //     value: slcM2oField
          //   }
          // ],
          funName: funName ?? '',
          title: this.renderOpts.props.cascadeFilter,
          from: 'cascadeFilter',
          data: { rows: currentRow }
        };
        Tsrv.doEvent(
          this.renderOpts.props.cascadeFilter,
          funInfo,
          () => p,
          false
        )
          .then(resp => {
            if (resp.isErr()) {
              console.error(resp.errmsg);
            }
            const data = resp.getReturnData(`conf`);
            if (!Tsrv.utils.noValue(data?.res.success) && !data.res.success) {
              console.error(data.res.msg);
            }
            const initFilter = data?.res?.data?.initFilter;
            if (!Tsrv.utils.noValue(initFilter)) {
              this.initFilter.push(initFilter);
            }
          })
          .catch(er => {
            console.error(er);
          });
      }
    }
  }

  private insertRow(data: any) {
    const table = this.params.$table.$parent.$parent;
    if (typeof table.insertRow === 'function') {
      data.forEach(el => {
        table.insertRow(-1, {
          data: el
        });
      });
    }
  }

  onDoChange() {
    // 如果magicbox为关闭状态
    if (this.isInTable) {
      // 表内
      if (this.value === '') {
        // 若显示值为空，则清空表值
        this.setTableValue(null);
        // 值确实改变
        this.emitEvent('dochange');
      } else {
        if (!this.notM2O) {
          // 若显示值不为空
          if (this.selectedM2oValue !== null && this.selectedValue !== null) {
            // 若存在已选择值/已选择m2o值，则为有效数据
            // 值确实改变
            this.emitEvent('dochange');
            // 设置显示值
            // this.value = Tsrv.getI18nBySrv(this.selectedM2oValue);
            this.value = this.i18n(this.selectedM2oValue);
          } else {
            // 若不存在已选择值/已选择m2o值，则为无效数据，则清空表值
            this.setTableValue(null);
            this.emitEvent('dochange');
          }
        } else {
          this.setTableValue(this.value);
          this.emitEvent('dochange');
        }
      }
    } else {
      // 非表内
      if (this.value === '') {
        // 显示值为空，则清空
        this.selectedM2oValue = '';
        this.selectedRow = null;
        this.$emit('model-change', null);
      } else {
        // 显示值不为空
        if (!this.notM2O) {
          if (this.selectedM2oValue !== '') {
            // 存在m2o值
            this.$emit('model-change', this.selectedM2oValue);

            // 设置显示值
            this.$nextTick(() => {
              // this.value = Tsrv.getI18nBySrv(this.selectedM2oValue);
              this.value = this.i18n(this.selectedM2oValue);
            });
          } else {
            // 不存在m2o值，则清空
            this.value = null;
            this.$emit('model-change', null);
          }
        } else {
          this.$emit('model-change', this.value);
          this.setTableValue(this.value);
        }
      }
      if (this.storedValue !== this.selectedM2oValue)
        this.emitEvent('dochange');
      this.storedValue = this.selectedM2oValue;
    }
  }

  private getFieldConfig() {
    let cfg = null;
    if (this.isInTable) {
      cfg = this.renderOpts.props.m2oConfig
        ? this.renderOpts.props.m2oConfig.fields
        : [];
    } else {
      cfg = this.option;
    }
    if (cfg) {
      if (this.isInTable) {
        return Tsrv.utils.getM2OConfigOption(
          cfg,
          this.params.property ? this.params.data : this.params.row
        );
      }
      return cfg;
    }
    return [];
  }

  /**
   * onBlur blur事件
   */
  onBlur() {
    if (this.currentBusId) {
      this.focus();
    } else {
      if (!this.isInTable && this.value === '') {
        this.$emit(`on-dochange`, null);
      }
      // this.onDoChange();
      this.emitEvent('blur');
    }
  }

  /**
   * onFocus focus事件
   */
  onFocus() {
    this.emitEvent('focus');
  }

  /**
   * onChange 正在输入
   */
  onChange(e) {
    const val = e?.target?.value || '';
    this.$emit(`model-change`, val);
    this.$emit(`on-dochange`, val);

    if (val === '') {
      this.onDoChange();
      this.setValue();
      this.$bus.$emit(`${this.currentBusId}_hide`);
    } else {
      this.openMagicBox(e, 'mini');
      // this.openMagicBox(e, this.boxMode || 'mini');
    }
  }

  onEnter(e) {
    this.emitEvent('enter');
  }

  onMouseleave(e) {
    this.emitEvent('mouseleave');
  }

  onMouseenter(e) {
    this.emitEvent('mouseenter');
  }

  /**
   * emitEvent 发送事件
   */
  emitEvent(event: string) {
    if (this.isInTable) {
      const ev = this.renderOpts.events;
      // 深拷贝有问题
      // const params = Tsrv.utils.clone(this.params);
      const params = Tsrv.utils.cloneNoMatchVue(this.params, true);
      params.from = 'm2o';
      for (const action in ev) {
        if (ev[action] && action === `on-${event}`) {
          // ev[action](params);
          ev[action](params, event);
        }
      }
      // 数据来源于表格 但使用是在表格外部使用该组件 时：父组件事件发送
      if (this.isFromTable && !Tsrv.utils.noValue(this.selectedRow)) {
        this.$emit(`on-${event}`, this.selectedRow);
      }
    } else {
      // this.$emit(`on-${event}`, this.selectedRow);
      // modify by wiz 如果没有选择不发事件
      if (!Tsrv.utils.noValue(this.selectedRow)) {
        this.$emit(`on-${event}`, this.selectedRow);
      }
    }
  }

  /**
   * focus 聚焦事件
   */
  public focus() {
    (this.$refs.input as Input).focus();
    ((this.$refs.input as Input).$el as HTMLInputElement).click();
  }

  private addCustomEvents() {
    ((this.$refs.input as Input).$el as HTMLInputElement).addEventListener(
      'mouseenter',
      this.onMouseenter
    );
    ((this.$refs.input as Input).$el as HTMLInputElement).addEventListener(
      'mouseleave',
      this.onMouseleave
    );
  }

  private destroyCustomEvents() {
    ((this.$refs.input as Input).$el as HTMLInputElement).removeEventListener(
      'mouseenter',
      this.onMouseenter
    );
    ((this.$refs.input as Input).$el as HTMLInputElement).removeEventListener(
      'mouseleave',
      this.onMouseleave
    );
  }

  beforeDestroy() {
    this.destroyCustomEvents();
  }

  public i18n(s: string): string {
    if (this.isI18n) {
      return Tsrv.getI18nBySrv(s);
    }
    return s;
  }
}
</script>
<style scoped lang="scss">
.item-render {
  width: calc(100% - 40px);
  position: absolute;
  top: 0;
  left: 8px;
  height: 100%;
  line-height: 30px;
  background-color: #fff;
}
.o-m2o-selector ::v-deep .ivu-icon {
  cursor: pointer;
}
</style>
